package com.apobates.forum.orize;

import javax.xml.bind.annotation.*;
import java.beans.Transient;
import java.io.Serializable;

/**
 * 资源/注解的方法需要收集的信息
 * {GET}   {/order/list/}{do}  {add}   {R1,R2}
 * {method}{path}       {spot} {action}{roles}
 * @author xiaofanku@live.cn
 * @since 20210822
 */
@XmlRootElement
@XmlType(propOrder = { "path", "method", "action", "roles", "spot", "slot", "slotKeys" })
public class OrizeResource implements Serializable {

    /**
     * 需要权限验证的url
     * 无查询参数,例:/order/create
     */
    private String path;

    /**
     * HTTP方法/GET、POST、PUT、DELETE
     */
    private String method;

    /**
     * 允许的角色列表,多个用逗号分隔
     */
    private String roles;

    /**
     * 请求参数中的标识
     * 当请求的地址用于复合操作时用于区分现在是在进行哪个操作
     * 例: /product/edit同时是新增和编辑的地址, spot是用于区分具体操作的查询字符串key(&do)
     */
    private String spot;

    /**
     * 操作名称
     * 当请求的地址用于复合操作时用于区分现在是在进行哪个操作
     * 例: /product/edit同时是新增和编辑的地址, action是用于区分具体的操作;spot的值(&do=add)
     */
    private String action;

    /**
     * 路径中是否存在占位符
     * 例:
     * /{id}.xhtml 存在
     * /edit 不存在
     * true存在/false不存在
     */
    private boolean slot;

    /**
     * 若存在占位符,占位的名称是什么
     * 例:/{id}.xhtml, slotKeys={"id"}
     * 多个用逗号分隔
     */
    private String slotKeys;

    public OrizeResource() {
    }

    /**
     *
     * @param path 请求的地址,无查询参数内部
     * @param method HTTP方法
     * @param roles 需要的角色,多个用逗号分隔
     * @param spot 从请求的地址中分解action的key
     * @param action 用于区分复合操作的名称,例如：新增和编辑是共用同一个地址
     */
    public OrizeResource(String path, String method, String roles, String spot, String action) {
        this.path = path;
        this.method = method;
        this.action = action;
        this.roles = roles;
        this.spot = spot;
        this.slot = false;
        this.slotKeys = "*";
    }

    /**
     *
     * @param path 请求的地址,无查询参数内部
     * @param method HTTP方法
     * @param roles 需要的角色,多个用逗号分隔
     * @param spot 从请求的地址中分解action的key
     * @param action 用于区分复合操作的名称,例如：新增和编辑是共用同一个地址
     * @param slot path中是否存在占位符,true存在
     * @param slotKeys 若存在占位符,占位的key
     */
    public OrizeResource(String path, String method, String roles, String spot, String action, boolean slot, String[] slotKeys) {
        this.path = path;
        this.method = method;
        this.roles = roles;
        this.spot = spot;
        this.action = action;
        this.slot = slot;
        this.slotKeys = (slot && slotKeys.length>0)?String.join(",", slotKeys):"*";
    }

    /**
     *
     * @param path 请求的地址,无查询参数内部
     * @param action 操作枚举,严格按照REST-ful的方法命名, method=OrizeAction.method, action=OrizeAction.name
     * @param roles 需要的角色
     */
    public OrizeResource(String path, OrizeAction action, String roles) {
        this.path = path;
        this.method = action.getMethod();
        this.action = action.name();
        this.roles = roles;
        this.spot = "do";
        this.slot = false;
        this.slotKeys = "*";
    }

    /**
     *
     * @param path 请求的地址,无查询参数内部
     * @param action 操作枚举,严格按照REST-ful的方法命名, method=OrizeAction.method, action=OrizeAction.name
     * @param roles 需要的角色
     * @param slot path中是否存在占位符,true存在
     * @param slotKeys 若存在占位符,占位的key
     */
    public OrizeResource(String path, OrizeAction action, String roles, boolean slot, String[] slotKeys) {
        this.path = path;
        this.method = action.getMethod();
        this.action = action.name();
        this.roles = roles;
        this.spot = "do";
        this.slot = slot;
        this.slotKeys = (slot && slotKeys.length>0)?String.join(",", slotKeys):"*";
    }

    @XmlElement(name = "path")
    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }

    @XmlElement(name = "method")
    public String getMethod() {
        return method;
    }

    public void setMethod(String method) {
        this.method = method;
    }

    @XmlElement(name = "spot")
    public String getSpot() {
        return spot;
    }

    public void setSpot(String spot) {
        this.spot = spot;
    }

    @XmlElement(name = "action")
    public String getAction() {
        return action;
    }

    public void setAction(String action) {
        this.action = action;
    }

    @XmlElement(name = "roles")
    public String getRoles() {
        return roles;
    }

    public void setRoles(String roles) {
        this.roles = roles;
    }

    @XmlElement(name = "slot")
    public boolean isSlot() {
        return slot;
    }

    public void setSlot(boolean slot) {
        this.slot = slot;
    }

    @XmlElement(name = "slotKeys")
    public String getSlotKeys() {
        return slotKeys;
    }

    public void setSlotKeys(String slotKeys) {
        this.slotKeys = slotKeys;
    }

    @XmlTransient
    public boolean isNotFind(){
        return "-".equals(getPath()) && "*".equals(getRoles());
    }

    public static OrizeResource notFind(){
        return new OrizeResource("-", "get", "*", "do", "view");
    }

}